"""
# -*- coding: utf-8 -*-
# @Time    : 2023/3/6 22:15
# @Author  : 王摇摆
# @FileName: cross_entropy_error_监督数据（标签混合版）.py
# @Software: PyCharm
# @Blog    ：https://blog.csdn.net/weixin_44943389?type=blog
"""
import os
import pickle
import sys

import numpy as np

from dataset.mnist import load_mnist

sys.path.append(os.pardir)


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=True)
    return x_train, t_train


def init_network():
    with open(file='sample_weight.pkl', mode='rb') as f:
        network = pickle.load(f)
    return network


def sigmod(x):
    y = 1 / (1 + np.exp(-x))
    return y


def softmax(x):
    exp_a = np.exp(x)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y


def predict(network, x):
    W1 = network['W1']
    W2 = network['W2']
    W3 = network['W3']

    b1 = network['b1']
    b2 = network['b2']
    b3 = network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmod(a1)

    a2 = np.dot(z1, W2) + b2
    z2 = sigmod(a2)

    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)
    return y


# 正确解是数组，区分输入是全部还是batch，都是二维矩阵，但是如果是一维向量，那就需要手动转为二维矩阵，才好使用numpy工具
def cross_entropy_error(y, t):
    if y.ndim == 1:
        y = y.reshape(1, y.size)  # 将y转为二维矩阵，并命令行元素为数量个数
        t = t.reshape(1, t.size)

    # use batches
    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size  # 返回值只有一个，通过*完成数量积，然后sum计算


# Accuracy_count计算神经网络预测结果的准确率
def accuracy_function(y, t):
    accuracy_count = 0

    predict_result = np.argmax(y, axis=1)
    correct_result = np.argmax(t, axis=1)

    for i in range(0, predict_result.shape[0]):
        if predict_result[i] == correct_result[i]:
            accuracy_count = accuracy_count + 1

    return accuracy_count / y.shape[0] * 100


if __name__ == '__main__':
    x, t = get_data()
    network = init_network()
    batch_size = 0  # Switch is on the here!

    # 先挑出数据，再参与神经网络预测推理
    if batch_size != 0:
        print('---本次使用了mnist_batch数据！---')
        random_data = np.random.choice(a=x.shape[0], size=batch_size)
        x = x[random_data]
        t = t[random_data]
        y = predict(network, x)

    else:
        y = predict(network, x)
        print('---本次使用了完整的mnist数据！---')

    error_result = cross_entropy_error(y, t)
    print('损失函数的值是： ' + str(error_result))

    accuracy = accuracy_function(y, t)
    print('神经网络预测结果的准确率是： ' + str(accuracy) + ' %')
